﻿using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Controls.Primitives;
using System.Windows.Input;

using MyUtils;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using XTrace.Registry;
using XTrace.Viewer.Properties;
using System.Windows.Media;
using System.IO;

namespace XTrace.Viewer
{
	partial class MainWindow
	{
		private Timer _timer;
		void CallBack(object state)
		{
			try
			{
				var app = Application.Current;
				if (app != null)
				{
					app.Dispatcher.BeginInvoke((Action)_windowContext.ReadAllRest);
				}
			}
			catch (Exception ex)
			{
				XTrace.Exception(ex);
			}
		}

		public MainWindow()
		{
			InitializeComponent();

			grid.SelectionChanged += GridSelectionChanged;
			grid.LoadingRow += grid_LoadingRow;

			Dispatcher.BeginInvoke((Action)delegate
			{
				DataContext = _windowContext = new WindowContext();
				_windowContext.Sources.PropertyChanged += SourcesPropertyChanged;
				_timer = new Timer(CallBack, null, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(2));

				ApplySettings();
				Settings.Default.PropertyChanged += SettingsChanged;
			}, System.Windows.Threading.DispatcherPriority.ApplicationIdle);
		}

		void SourcesPropertyChanged(object sender, PropertyChangedEventArgs e)
		{
			if (string.IsNullOrWhiteSpace(e.PropertyName) || e.PropertyName == "SelectedSource")
			{
				var s = _windowContext.Sources.SelectedSource;
				if (s == null)
				{
					Title = "XTrace";
				}
				else
				{
					Title = "XTrace: " + s.FullPath;
				}
			}
		}

		void grid_LoadingRow(object sender, DataGridRowEventArgs e)
		{
			var ev = (XTraceEvent)e.Row.DataContext;
			var bgBrush = GetBgColor(ev);
			if (bgBrush != null)
			{
				e.Row.Background = bgBrush;
			}
			var fgBrush = GetFgColor(ev);
			if (fgBrush != null)
			{
				e.Row.Foreground = fgBrush;
			}
		}

		#region Brushes

		Brush _bgWarning;
		Brush BgWarning
		{
			get
			{
				return _bgWarning ?? (_bgWarning = (Brush)Resources["bgWarning"]);
			}
		}

		Brush _bgError;
		Brush BgError
		{
			get
			{
				return _bgError ?? (_bgError = (Brush)Resources["bgError"]);
			}
		}

		Brush _bgImportant;
		Brush BgImportant
		{
			get
			{
				return _bgImportant ?? (_bgImportant = (Brush)Resources["bgImportant"]);
			}
		}

		Brush _bgInformation;
		Brush BgInformation
		{
			get
			{
				return _bgInformation ?? (_bgInformation = (Brush)Resources["bgInformation"]);
			}
		}

		Brush _bgVerbose;
		Brush BgVerbose
		{
			get
			{
				return _bgVerbose ?? (_bgVerbose = (Brush)Resources["bgVerbose"]);
			}
		}

		#endregion

		Brush GetBgColor(XTraceEvent ev)
		{
			if(ev.Level<=XTraceLevel.Error)
			{
				return BgError;
			}
			if (ev.Level <= XTraceLevel.Exception)
			{
				return BgError;
			}
			if (ev.Level <= XTraceLevel.Warning)
			{
				return BgWarning;
			}
			if (ev.Level <= XTraceLevel.Important)
			{
				return BgImportant;
			}
			if (ev.Level <= XTraceLevel.Information)
			{
				return BgInformation;
			}
			return BgVerbose;
		}

		static Brush GetFgColor(XTraceEvent ev)
		{
			return Brushes.Black;
//			if (ev.Level <= XTraceLevel.Error)
//			{
//				return Brushes.Pink;
//			}
//			if (ev.Level <= XTraceLevel.Exception)
//			{
//				return Brushes.Pink;
//			}
//			if (ev.Level <= XTraceLevel.Warning)
//			{
//				return Brushes.Black;
//			}
//			if (ev.Level <= XTraceLevel.Information)
//			{
//				return Brushes.Blue;
//			}
//			return Brushes.LightGray;
		}

		int _lastId = -1;
		void GridSelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			var ssfevm = grid.SelectedIndex;

			if (_lastId != ssfevm)
			{
				if (ssfevm >= 0)
				{
					grid.ScrollIntoView(grid.Items[ssfevm]);
				}
			}
			_lastId = ssfevm;
		}

		WindowContext _windowContext;

		static readonly XTraceSource _trace = new XTraceSource("MainForm");

		void SettingsChanged(object sender, PropertyChangedEventArgs e)
		{
			_trace.Information("SettingsChanged", "{0} = {1}", e.PropertyName, Settings.Default.GetType().GetProperty(e.PropertyName).GetValue(Settings.Default, null));
			ApplySettings();
		}

		void ApplySettings()
		{
			Topmost = Settings.Default.AllwaysOnTop;
			Settings.Default.Save();

			if (Settings.Default.Follow)
			{
				_windowContext.SelectLastRow();
			}
		}

		private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
		{
			if (e.PropertyName == "CallStack")
			{
				e.Cancel = true;
			}
			else if (e.PropertyName == "EventId")
			{
				e.Column.CellStyle = (Style)Resources["EventIdCellStyle"];
			}
			//			BindingOperations.SetBinding(e.Column, DataGridColumn.VisibilityProperty, new Binding("IsVisible")
			//			{
			//				Source = _windowContext.ColumnSettings.First(x => x.Name == e.PropertyName),
			//				Converter = new BooleanToVisibilityConverter(),
			//			});
		}

		private void MarkForRemoval(object sender, RoutedEventArgs e)
		{
			_windowContext.MarkForClear();
		}

		private void MarkForRemovalAll(object sender, RoutedEventArgs e)
		{
			_windowContext.MarkForClearAll();
		}

		private void Reopen(object sender, RoutedEventArgs e)
		{
			_windowContext.Reopen();
		}

		private void Window_DragEnter(object sender, DragEventArgs e)
		{
			if (e.Data.GetDataPresent("FileDrop"))
			{
				e.Effects = DragDropEffects.Copy;
			}
		}

		private void Window_Drop(object sender, DragEventArgs e)
		{
			var datas = e.Data.GetData("FileDrop") as string[];
			foreach (var data in datas)
			{
				_windowContext.Sources.SwitchTo(data);
			}
		}

		private void CopySelectedEvent(object sender, RoutedEventArgs e)
		{
			var ev = grid.SelectedItem as XTraceEvent;
			if (ev != null)
			{
				for (int i = 0; i < 3; i++)
				{
					try
					{
						Clipboard.SetText(ev.ToString());
						break;
					}
					catch (ExternalException)
					{
						Thread.Sleep(1000.Random());
					}
				}

			}
		}

		private void ApplyFilter(object sender, RoutedEventArgs e)
		{
			_windowContext.Refilter();
		}

		private void MenuItem_ExcludeThisEvents_OnClick(object sender, RoutedEventArgs e)
		{
			ExcludeThisEvents(sender);
		}

		void ExcludeThisEvents(object sender)
		{
			var element = (FrameworkElement)sender;
			var ev = (XTraceEvent)element.DataContext;
			var eventIdsFilter = _windowContext.FilterModel.GetStringSetFilter("EventId");
			var ssfvm = _windowContext.StringSetFilters.First(x => x.FieldName == "EventId");
			var ssfevm = ssfvm.EntriesNonFiltered.FirstOrDefault(x => x.Name == ev.EventId);
			if (ssfevm != null)
			{
				ssfevm.IsExcluded = true;
			}
			_windowContext.ShowFilter = true;

			if (eventIdsFilter.All)
			{
				eventIdsFilter.UseExcludes = true;
			}
			else if (eventIdsFilter.UseIncludes && eventIdsFilter.IncludesHashSet.Count == 0)
			{
				eventIdsFilter.UseExcludes = true;
			}
			_windowContext.Refilter();
		}

		private void Spam_Image_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
		{
			ExcludeThisEvents(sender);
		}
	}

	public class AutoColumnBehavior : DependencyObject
	{
		public static DependencyProperty IsAdvancedProperty = DependencyProperty.RegisterAttached("IsAdvanced", typeof(bool), typeof(AutoColumnBehavior), new PropertyMetadata(Changed));

		public bool IsAdvanced
		{
			get { return (bool)GetValue(IsAdvancedProperty); }
			set { SetValue(IsAdvancedProperty, value); }
		}

		public AutoColumnBehavior()
		{
			Console.WriteLine(5);
		}

		static void Changed(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
		{
			var header = (DataGridColumnHeader)dependencyObject;
			header.MouseRightButtonDown += HeaderMouseRightButtonDown;
		}

		static void HeaderMouseRightButtonDown(object sender, MouseButtonEventArgs e)
		{
			var header = (DataGridColumnHeader)sender;
			header.Width = 100;
		}
	}
}

